package com.yykj.hospital.server.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.yykj.common.enums.BanCiType;
import com.yykj.common.enums.ResultEnums;
import com.yykj.common.enums.TemplateType;
import com.yykj.common.exception.NormalException;
import com.yykj.common.util.FileWithExcelUtil;
import com.yykj.common.vo.PageData;
import com.yykj.common.vo.ResultVO;
import com.yykj.hospital.client.dto.banci.DoctorBanCiOnlineListDTO;
import com.yykj.hospital.client.dto.banci.HospitalBanCiDTO;
import com.yykj.hospital.client.form.banci.BanCIListFrom;
import com.yykj.hospital.client.form.banci.BanCiEditForm;
import com.yykj.hospital.server.converter.DoctorBanCiAppointmentListDTOConverter;
import com.yykj.hospital.server.converter.DoctorBanCiOnlineListDTOConverter;
import com.yykj.hospital.server.dto.banci.*;
import com.yykj.hospital.server.form.DoctorBanCiEditForm;
import com.yykj.hospital.server.form.DoctorVisitForm;
import com.yykj.hospital.server.form.DoctorVisitLevelForm;
import com.yykj.hospital.server.form.DoctorVisitSettingSearchForm;
import com.yykj.hospital.server.handler.DoctorAppointmentSettingHandler;
import com.yykj.hospital.server.handler.DoctorOnlineVisitSettingHandler;
import com.yykj.hospital.server.model.entity.banci.HospitalDoctorBanCi;
import com.yykj.hospital.server.service.banci.BanCiExportService;
import com.yykj.hospital.server.service.banci.BanCiImportService;
import com.yykj.hospital.server.service.banci.BanCiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@RestController
@RequestMapping("/api/backstage/hospital")
@SuppressWarnings("unchecked")
@Api(tags = "班次相关接口")
public class HospitalBanCiController {
    @GetMapping("/banci/list")
    @ApiOperation("班次管理--列表")
    public ResultVO<List<HospitalBanCiDTO>> getBanCiList(
            @RequestParam(name = "hospitalId") Integer hospitalId,
            @RequestParam(name = "keyword", required = false) String keyword,
            @RequestParam(name = "type") BanCiType type) {
        return ResultVO.success(banCiService.listBanCi(hospitalId, type, keyword));
    }

    @PostMapping("/banci/add")
    @ApiOperation("班次管理--添加")
    @ApiOperationSupport(ignoreParameters = {"id"})
    public ResultVO<HospitalBanCiDTO> addBanCi(@RequestBody BanCiEditForm form) {
        return ResultVO.success(banCiService.editBanCi(form));
    }

    @PostMapping("/banci/edit")
    @ApiOperation("班次管理--修改")
    public ResultVO<HospitalBanCiDTO> editBanCi(@RequestBody BanCiEditForm form) {
        return ResultVO.success(banCiService.editBanCi(form));
    }
    //=======================================================================================================

    @PostMapping("/visit/level/add")
    @ApiOperation("出诊级别--添加")
    @ApiOperationSupport(ignoreParameters = {"id"})
    public ResultVO<DoctorVisitLevelDTO> addDoctorVisitLevel(@RequestBody DoctorVisitLevelForm form) {
        return ResultVO.success(banCiService.editDoctorVisitLevel(form));
    }

    @PutMapping("/visit/level/edit")
    @ApiOperation("出诊级别--修改")
    public ResultVO<DoctorVisitLevelDTO> editDoctorVisitLevel(@RequestBody DoctorVisitLevelForm form) {
        return ResultVO.success(banCiService.editDoctorVisitLevel(form));
    }

    @GetMapping("/visit/level/list")
    @ApiOperation("出诊级别--列表")
    public ResultVO<List<DoctorVisitLevelDTO>> listDoctorVisitLevel(
            @RequestParam(name = "hospitalId") Integer hospitalId,
            @RequestParam(name = "keyword", required = false) String keyword) {
        return ResultVO.success(banCiService.listDoctorVisitLevel(hospitalId, true, keyword));
    }

    //=======================================================================================================
    @PostMapping("/visit/add")
    @ApiOperation("出诊设置--添加")
    @ApiOperationSupport(ignoreParameters = {"id"})
    public ResultVO<DoctorVisitSettingDTO> addDoctorVisit(@RequestBody DoctorVisitForm form) {
        return ResultVO.success(banCiService.editDoctorVisit(form));
    }

    @PutMapping("/visit/edit")
    @ApiOperation("出诊设置--修改")
    public ResultVO<DoctorVisitSettingDTO> editDoctorVisit(@RequestBody DoctorVisitForm form) {
        return ResultVO.success(banCiService.editDoctorVisit(form));
    }

    @GetMapping("/visit/list")
    @ApiOperation("出诊设置--列表")
    public ResultVO<PageData<DoctorVisitSettingDTO>> listDoctorVisit(
            @RequestParam(value = "hospitalId", required = true) Integer hospitalId,
            @RequestParam(value = "depId", required = false) Integer depId,
            @RequestParam(value = "levelId", required = false) Integer levelId,
            @RequestParam(value = "doctorId", required = false) String doctorId,
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "currentPage", required = false,defaultValue = "1") Integer currentPage,
            @RequestParam(value = "pageSize", required = false,defaultValue = "10") Integer pageSize,
            @RequestParam(value = "type") BanCiType type) {

        DoctorVisitSettingSearchForm form = DoctorVisitSettingSearchForm.builder()
                .hospitalId(hospitalId)
                .doctorId(doctorId)
                .levelId(levelId)
                .depId(depId)
                .keyword(keyword)
                .type(type)
                .currentPage(currentPage)
                .pageSize(pageSize)
                .build();
        return ResultVO.success(banCiService.listDoctorVisitSetting(form));
    }

    @PostMapping("/visit/online/upload")
    @ApiOperation("出诊设置--在线问诊--导入")
    public ResultVO uploadOnlineExcel(Integer hospitalId, MultipartFile file) {
        try {
            DoctorOnlineVisitSettingHandler onlineVisitSettingHandler = new DoctorOnlineVisitSettingHandler();
            ImportParams params = new ImportParams();
            params.setVerifyHandler(onlineVisitSettingHandler);
            params.setNeedVerify(true);
            ExcelImportResult<SettingImportDTO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), SettingImportDTO.class, params);
            if (result.isVerifyFail()) {
                return ResultVO.error(result.getFailList());
            } else {
                boolean b = banCiImportService.checkOnlineVisitSetting(hospitalId, result);
                if (b) {
                    banCiImportService.importOnlineVisitSetting(hospitalId, result.getList());
                    return ResultVO.success(result.getList());
                } else {
                    return ResultVO.error(result.getFailList());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("请按照模板正确填写");
        }
    }

    @PostMapping("/visit/appointment/upload")
    @ApiOperation("出诊设置--预约挂号--导入")
    public ResultVO uploadAppointmentExcel(Integer hospitalId, MultipartFile file) {
        try {
            DoctorAppointmentSettingHandler handler = new DoctorAppointmentSettingHandler();
            ImportParams params = new ImportParams();
            params.setVerifyHandler(handler);
            params.setNeedVerify(true);
            ExcelImportResult<SettingImportDTO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), SettingImportDTO.class, params);
            if (result.isVerifyFail()) {
                return ResultVO.error(result.getFailList());
            } else {
                boolean b = banCiImportService.checkAppointmentVisitSetting(hospitalId, result);
                if (b) {
                    banCiImportService.importAppointmentVisitSetting(hospitalId, result.getList());
                    return ResultVO.success(result.getList());
                } else {
                    return ResultVO.error(result.getFailList());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @GetMapping("/visit/template/url/{type}")
    @ApiOperation("出诊设置--模板下载")
    public ResultVO<String> downloadFile(@PathVariable TemplateType type)
            throws IOException {

//        InputStream inputStream  = null;
        String url = null;
        switch (type) {
            case online:
//                inputStream = this.getClass().getClassLoader().getResourceAsStream("template/visit_template_online.xlsx");
                url = "https://yykj-1307182424.cos.ap-shanghai.myqcloud.com/static/template/visit_template_online.xlsx";
                break;
            case appointment:
//                inputStream = this.getClass().getClassLoader().getResourceAsStream("template/visit_template_appointment.xlsx");
                url = "https://yykj-1307182424.cos.ap-shanghai.myqcloud.com/static/template/visit_template_appointment.xlsx";
                break;
            default:
                throw new NormalException(ResultEnums.PARAM_ERROR);
        }
        return ResultVO.success(url);
//
//        HttpHeaders headers = new HttpHeaders();
//        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
//        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", "template.xlsx"));
//        headers.add("Pragma", "no-cache");
//        headers.add("Expires", "0");
//
//        return ResponseEntity
//                .ok()
//                .headers(headers)
//                .contentLength(inputStream.available())
//                .contentType(MediaType.parseMediaType("application/octet-stream"))
//                .body(new InputStreamResource(inputStream));
    }

    //=======================================================================================================
    @GetMapping("/doctor/online/banci/list")
    @ApiOperation("在线问诊-排班生成--列表")
    public ResultVO<DoctorBanCiOnlineListDTO> getDoctorBanCi(
            @RequestParam(name = "hospitalId", required = true) Integer hospitalId,
            @RequestParam(name = "depId", required = false) Integer depId,
            @RequestParam(name = "doctorId", required = false) String doctorId,
            @RequestParam(name = "startDate") String startDate,
            @RequestParam(name = "endDate") String endDate) {

        BanCIListFrom form = BanCIListFrom.builder()
                .hospitalId(hospitalId)
                .depId(depId)
                .doctorId(doctorId)
                .startDate(startDate)
                .endDate(endDate)
                .type(BanCiType.online)
                .build();
        List<HospitalDoctorBanCi> doctorBanCiList = banCiService.getDoctorBanCiList(form);
        return ResultVO.success(DoctorBanCiOnlineListDTOConverter.convert(doctorBanCiList));
    }

    @PostMapping("/doctor/online/banci/adjust")
    @ApiOperation("在线问诊-排班调整--添加")
    public ResultVO<DoctorBanCiOnlineListDTO> adjustOnlineBanCi(@RequestBody AdjustOnlineBanCiForm form) {
        banCiService.adjustOnlineBanCi(form);
        return ResultVO.success();
    }

    @PostMapping("/doctor/online/banci/edit")
    @ApiOperation("在线问诊-排班生成--添加修改")
    @ApiOperationSupport(ignoreParameters = {"list[0].data[0].data[0].appointment", "type"})
    public ResultVO<List<DoctorBanCiDTO>> editDoctorOnLineBanCi(@RequestBody DoctorBanCiEditForm form) {
        form.setType(BanCiType.online);
        return ResultVO.success(banCiService.editDoctorBanCi(form));
    }

    @GetMapping("/doctor/online/banci/export")
    @ApiOperation("在线问诊--排班报表--导出")
    public void exportOnline(HttpServletResponse response,
                             @RequestParam(name = "hospitalId", required = true) Integer hospitalId,
                             @RequestParam(name = "doctorId", required = false) String doctorId,
                             @RequestParam(name = "depId", required = false) Integer depId,
                             @RequestParam(name = "startDate", required = false) String startDate,
                             @RequestParam(name = "endDate", required = false) String endDate,
                             @RequestParam(name = "keyword", required = false) String keyword
    ) throws Exception {

        BanCIListFrom from = BanCIListFrom.builder()
                .hospitalId(hospitalId)
                .doctorId(doctorId)
                .depId(depId)
                .startDate(startDate)
                .endDate(endDate)
                .keyword(keyword)
                .type(BanCiType.online)
                .build();
        Workbook workbook = banCiExportService.exportDoctorOnlineBanCi(from);

        FileWithExcelUtil.downLoadExcel("在线问诊班次", response, workbook);

    }


    @GetMapping("/doctor/appointment/banci/export")
    @ApiOperation("预约挂号--排班报表--导出")
    public void exportAppointment(HttpServletResponse response,
                                  @RequestParam(name = "hospitalId", required = true) Integer hospitalId,
                                  @RequestParam(name = "doctorId", required = false) String doctorId,
                                  @RequestParam(name = "depId", required = false) Integer depId,
                                  @RequestParam(name = "startDate", required = false) String startDate,
                                  @RequestParam(name = "endDate", required = false) String endDate,
                                  @RequestParam(name = "keyword", required = false) String keyword
    ) throws Exception {

        BanCIListFrom form = BanCIListFrom.builder()
                .hospitalId(hospitalId)
                .doctorId(doctorId)
                .depId(depId)
                .startDate(startDate)
                .endDate(endDate)
                .keyword(keyword)
                .type(BanCiType.appointment)
                .build();
        Workbook workbook = banCiExportService.exportDoctorAppointmentBanCi(form);

        FileWithExcelUtil.downLoadExcel("预约挂号班次", response, workbook);

    }

    @PostMapping("/doctor/appointment/banci/adjust")
    @ApiOperation("预约挂号-排班调整--添加")
    public ResultVO<DoctorBanCiOnlineListDTO> adjustAppointmentBanCi(@RequestBody AdjustAppointmentBanCiForm form) {
        banCiService.adjustAppointmentBanCi(form);
        return ResultVO.success();
    }

    @PostMapping("/doctor/appointment/banci/edit")
    @ApiOperation("预约挂号-排班生成--添加修改")
    @ApiOperationSupport(ignoreParameters = {"list[0].data[0].data[0].pic", "list[0].data[0].data[0].voice", "list[0].data[0].data[0].video", "type"})
    public ResultVO editDoctorAppointBanCi(@RequestBody DoctorBanCiEditForm form) {
        form.setType(BanCiType.appointment);
        banCiService.editDoctorBanCi(form);
        return ResultVO.success();
    }

    @GetMapping("/doctor/appointment/banci/list")
    @ApiOperation("预约挂号-排班生成--列表")
    public ResultVO<DoctorBanCiOnlineListDTO> getDoctorBanCiAppointment(
            @RequestParam(name = "hospitalId", required = true) Integer hospitalId,
            @RequestParam(name = "depId", required = false) Integer depId,
            @RequestParam(name = "doctorId", required = false) String doctorId,
            @RequestParam(name = "startDate") String startDate,
            @RequestParam(name = "endDate") String endDate) {

        BanCIListFrom form = BanCIListFrom.builder()
                .hospitalId(hospitalId)
                .depId(depId)
                .doctorId(doctorId)
                .startDate(startDate)
                .endDate(endDate)
                .type(BanCiType.appointment)
                .build();
        List<HospitalDoctorBanCi> doctorBanCiList = banCiService.getDoctorBanCiList(form);
        return ResultVO.success(DoctorBanCiAppointmentListDTOConverter.convert(doctorBanCiList));
    }

    private BanCiService banCiService;

    private BanCiExportService banCiExportService;

    private BanCiImportService banCiImportService;

    @Autowired
    public void setBanCiService(BanCiService banCiService) {
        this.banCiService = banCiService;
    }

    @Autowired
    public void setBanCiExportService(BanCiExportService banCiExportService) {
        this.banCiExportService = banCiExportService;
    }

    @Autowired
    public void setBanCiImportService(BanCiImportService banCiImportService) {
        this.banCiImportService = banCiImportService;
    }
}
